﻿using System.Drawing;
using System.Drawing.Drawing2D;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Drawing.Imaging;

namespace Marbles.Core.Content.Captcha
{
    // CaptchaImage class adapted from http://www.codeproject.com/KB/aspnet/CaptchaImage.aspx 
    //
    public class CaptchaImage
    {
        public string ContentType { get { return "image/jpeg"; } }
        public string Code { get { return _code; } }

        private Bitmap bmp = null;
        private string _code = string.Empty;
        private Random random = null;

        public CaptchaImage(Int32 width, Int32 height, Int32 codesize)
        {
            random = new Random();
            bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            _code = GenerateCode(codesize);
            GenerateImage("Century Schoolbook");
        }

        public CaptchaImage(Int32 width, Int32 height, string Code)
        {
            random = new Random();
            bmp = new Bitmap(width, height, PixelFormat.Format32bppArgb);
            _code = Code;
            GenerateImage("Century Schoolbook");
        }

        //Code generation modified to work on a GUID this gives a random base up to 32 characters.
        private string GenerateCode(Int32 codesize)
        {
            string basecode = Guid.NewGuid().ToString("N");
            string s = "";
            for (int i = 0; i < codesize; i++)
            {
                //s = String.Concat(s, this.random.Next(10).ToString());
                s = string.Concat(s, basecode.Substring(this.random.Next(basecode.Length), 1));
            }
            return s;
        }

        private void GenerateImage(string fontFamily)
        {
            // Create a graphics object for drawing.
            Graphics g = Graphics.FromImage(bmp);
            g.SmoothingMode = SmoothingMode.AntiAlias;
            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);

            // Fill in the background.
            HatchBrush hatchBrush = new HatchBrush(HatchStyle.SmallConfetti, Color.LightGray, Color.White);
            g.FillRectangle(hatchBrush, rect);

            // Set up the text font.
            SizeF size;
            float fontSize = rect.Height + 1;
            Font font;
            // Adjust the font size until the text fits within the image.
            do
            {
                fontSize--;
                font = new Font(fontFamily, fontSize, FontStyle.Bold);
                size = g.MeasureString(this._code, font);
            } while (size.Width > rect.Width);

            // Set up the text format.
            StringFormat format = new StringFormat();
            format.Alignment = StringAlignment.Center;
            format.LineAlignment = StringAlignment.Center;

            // Create a path using the text and warp it randomly.
            GraphicsPath path = new GraphicsPath();
            path.AddString(this._code, font.FontFamily, (int)font.Style, font.Size, rect, format);
            float v = 4F;
            PointF[] points ={
        new PointF(this.random.Next(rect.Width) / v,this.random.Next(rect.Height) / v),
        new PointF(rect.Width - this.random.Next(rect.Width) / v,this.random.Next(rect.Height) / v),
        new PointF(this.random.Next(rect.Width) / v,rect.Height - this.random.Next(rect.Height) / v),
        new PointF(rect.Width - this.random.Next(rect.Width) / v,rect.Height - this.random.Next(rect.Height) / v)
      };
            Matrix matrix = new Matrix();
            matrix.Translate(0F, 0F);
            path.Warp(points, rect, matrix, WarpMode.Perspective, 0F);

            // Draw the text.
            hatchBrush = new HatchBrush(
              HatchStyle.LargeConfetti,
              Color.LightGray,
              Color.DarkGray);
            g.FillPath(hatchBrush, path);

            // Add some random noise.
            int m = Math.Max(rect.Width, rect.Height);
            for (int i = 0; i < (int)(rect.Width * rect.Height / 30F); i++)
            {
                int x = this.random.Next(rect.Width);
                int y = this.random.Next(rect.Height);
                int w = this.random.Next(m / 50);
                int h = this.random.Next(m / 50);
                g.FillEllipse(hatchBrush, x, y, w, h);
            }

            // Clean up.
            font.Dispose();
            hatchBrush.Dispose();
            g.Dispose();
        }

        public void Save(System.IO.Stream Stream)
        {
            bmp.Save(Stream, System.Drawing.Imaging.ImageFormat.Jpeg);
        }

    }
}